const { DataTypes } = require('sequelize');
const bcrypt = require('bcryptjs');
const { sequelize } = require('../config/database');
const config = require('../config/config');
const logger = require('../config/logger');

// 用户模型定义
const User = sequelize.define('User', {
  id: {
    type: DataTypes.UUID,
    defaultValue: DataTypes.UUIDV4,
    primaryKey: true,
    comment: '用户唯一标识'
  },
  
  // 基本信息
  username: {
    type: DataTypes.STRING(50),
    allowNull: false,
    unique: true,
    validate: {
      len: [3, 50],
      isAlphanumeric: {
        msg: '用户名只能包含字母和数字'
      }
    },
    comment: '用户名'
  },
  
  email: {
    type: DataTypes.STRING(100),
    allowNull: false,
    unique: true,
    validate: {
      isEmail: {
        msg: '请输入有效的邮箱地址'
      }
    },
    comment: '邮箱地址'
  },
  
  phone: {
    type: DataTypes.STRING(20),
    allowNull: true,
    unique: true,
    validate: {
      is: {
        args: /^[1][3-9]\d{9}$/,
        msg: '请输入有效的手机号码'
      }
    },
    comment: '手机号码'
  },
  
  password: {
    type: DataTypes.STRING(255),
    allowNull: false,
    validate: {
      len: {
        args: [config.security.passwordMinLength, config.security.passwordMaxLength],
        msg: `密码长度必须在${config.security.passwordMinLength}-${config.security.passwordMaxLength}个字符之间`
      }
    },
    comment: '密码哈希'
  },
  
  // 个人信息
  realName: {
    type: DataTypes.STRING(50),
    allowNull: true,
    validate: {
      len: [1, 50]
    },
    comment: '真实姓名'
  },
  
  nickname: {
    type: DataTypes.STRING(50),
    allowNull: true,
    validate: {
      len: [1, 50]
    },
    comment: '昵称'
  },
  
  avatar: {
    type: DataTypes.TEXT,
    allowNull: true,
    comment: '头像URL'
  },
  
  gender: {
    type: DataTypes.ENUM('male', 'female', 'other'),
    allowNull: true,
    comment: '性别'
  },
  
  birthday: {
    type: DataTypes.DATEONLY,
    allowNull: true,
    comment: '生日'
  },
  
  bio: {
    type: DataTypes.TEXT,
    allowNull: true,
    comment: '个人简介'
  },
  
  // 角色和权限
  role: {
    type: DataTypes.ENUM('student', 'teacher', 'admin', 'super_admin'),
    allowNull: false,
    defaultValue: 'student',
    comment: '用户角色'
  },
  
  permissions: {
    type: DataTypes.JSON,
    allowNull: true,
    defaultValue: [],
    comment: '用户权限列表'
  },
  
  // 状态信息
  status: {
    type: DataTypes.ENUM('active', 'inactive', 'suspended', 'deleted'),
    allowNull: false,
    defaultValue: 'active',
    comment: '用户状态'
  },
  
  emailVerified: {
    type: DataTypes.BOOLEAN,
    allowNull: false,
    defaultValue: false,
    comment: '邮箱是否已验证'
  },
  
  phoneVerified: {
    type: DataTypes.BOOLEAN,
    allowNull: false,
    defaultValue: false,
    comment: '手机号是否已验证'
  },
  
  // 安全信息
  loginAttempts: {
    type: DataTypes.INTEGER,
    allowNull: false,
    defaultValue: 0,
    comment: '登录尝试次数'
  },
  
  lockUntil: {
    type: DataTypes.DATE,
    allowNull: true,
    comment: '账户锁定到期时间'
  },
  
  lastLoginAt: {
    type: DataTypes.DATE,
    allowNull: true,
    comment: '最后登录时间'
  },
  
  lastLoginIp: {
    type: DataTypes.STRING(45),
    allowNull: true,
    comment: '最后登录IP'
  },
  
  // 验证码相关
  emailVerificationToken: {
    type: DataTypes.STRING(255),
    allowNull: true,
    comment: '邮箱验证令牌'
  },
  
  emailVerificationExpires: {
    type: DataTypes.DATE,
    allowNull: true,
    comment: '邮箱验证令牌过期时间'
  },
  
  passwordResetToken: {
    type: DataTypes.STRING(255),
    allowNull: true,
    comment: '密码重置令牌'
  },
  
  passwordResetExpires: {
    type: DataTypes.DATE,
    allowNull: true,
    comment: '密码重置令牌过期时间'
  },
  
  // 学习相关
  totalStudyTime: {
    type: DataTypes.INTEGER,
    allowNull: false,
    defaultValue: 0,
    comment: '总学习时长（分钟）'
  },
  
  totalCourses: {
    type: DataTypes.INTEGER,
    allowNull: false,
    defaultValue: 0,
    comment: '总课程数'
  },
  
  completedCourses: {
    type: DataTypes.INTEGER,
    allowNull: false,
    defaultValue: 0,
    comment: '已完成课程数'
  },
  
  totalExams: {
    type: DataTypes.INTEGER,
    allowNull: false,
    defaultValue: 0,
    comment: '总考试次数'
  },
  
  passedExams: {
    type: DataTypes.INTEGER,
    allowNull: false,
    defaultValue: 0,
    comment: '通过考试次数'
  },
  
  totalCertificates: {
    type: DataTypes.INTEGER,
    allowNull: false,
    defaultValue: 0,
    comment: '获得证书数'
  },
  
  // 偏好设置
  preferences: {
    type: DataTypes.JSON,
    allowNull: true,
    defaultValue: {
      language: 'zh-CN',
      timezone: 'Asia/Shanghai',
      theme: 'light',
      notifications: {
        email: true,
        sms: false,
        push: true
      }
    },
    comment: '用户偏好设置'
  },
  
  // 扩展字段
  metadata: {
    type: DataTypes.JSON,
    allowNull: true,
    defaultValue: {},
    comment: '扩展元数据'
  }
}, {
  tableName: 'users',
  timestamps: true,
  paranoid: true, // 软删除
  indexes: [
    {
      unique: true,
      fields: ['username']
    },
    {
      unique: true,
      fields: ['email']
    },
    {
      unique: true,
      fields: ['phone'],
      where: {
        phone: {
          [sequelize.Sequelize.Op.ne]: null
        }
      }
    },
    {
      fields: ['role']
    },
    {
      fields: ['status']
    }
  ]
});

// 实例方法
User.prototype.toJSON = function() {
  const values = { ...this.get() };
  
  // 移除敏感信息
  delete values.password;
  delete values.emailVerificationToken;
  delete values.emailVerificationExpires;
  delete values.passwordResetToken;
  delete values.passwordResetExpires;
  delete values.loginAttempts;
  delete values.lockUntil;
  
  return values;
};

// 验证密码
User.prototype.validatePassword = async function(password) {
  try {
    return await bcrypt.compare(password, this.password);
  } catch (error) {
    logger.error('密码验证失败:', error);
    return false;
  }
};

// 检查账户是否被锁定
User.prototype.isLocked = function() {
  return !!(this.lockUntil && this.lockUntil > Date.now());
};

// 增加登录尝试次数
User.prototype.incrementLoginAttempts = async function() {
  // 如果已经锁定且锁定时间已过，重置计数器
  if (this.lockUntil && this.lockUntil < Date.now()) {
    return this.update({
      loginAttempts: 1,
      lockUntil: null
    });
  }
  
  const updates = { loginAttempts: this.loginAttempts + 1 };
  
  // 如果达到最大尝试次数，锁定账户
  if (this.loginAttempts + 1 >= config.security.maxLoginAttempts) {
    updates.lockUntil = new Date(Date.now() + config.security.lockoutTime);
  }
  
  return this.update(updates);
};

// 重置登录尝试次数
User.prototype.resetLoginAttempts = async function() {
  return this.update({
    loginAttempts: 0,
    lockUntil: null
  });
};

// 更新最后登录信息
User.prototype.updateLastLogin = async function(ip) {
  return this.update({
    lastLoginAt: new Date(),
    lastLoginIp: ip
  });
};

// 生成邮箱验证令牌
User.prototype.generateEmailVerificationToken = function() {
  const crypto = require('crypto');
  const token = crypto.randomBytes(32).toString('hex');
  
  this.emailVerificationToken = token;
  this.emailVerificationExpires = new Date(Date.now() + config.security.verificationCodeExpiry);
  
  return token;
};

// 生成密码重置令牌
User.prototype.generatePasswordResetToken = function() {
  const crypto = require('crypto');
  const token = crypto.randomBytes(32).toString('hex');
  
  this.passwordResetToken = token;
  this.passwordResetExpires = new Date(Date.now() + config.security.resetPasswordExpiry);
  
  return token;
};

// 验证邮箱验证令牌
User.prototype.verifyEmailToken = function(token) {
  return this.emailVerificationToken === token && 
         this.emailVerificationExpires > new Date();
};

// 验证密码重置令牌
User.prototype.verifyPasswordResetToken = function(token) {
  return this.passwordResetToken === token && 
         this.passwordResetExpires > new Date();
};

// 获取用户权限
User.prototype.getPermissions = function() {
  const rolePermissions = {
    student: ['course:read', 'exam:take', 'profile:update'],
    teacher: ['course:read', 'course:create', 'course:update', 'exam:create', 'exam:update', 'student:read'],
    admin: ['*'],
    super_admin: ['*']
  };
  
  const basePermissions = rolePermissions[this.role] || [];
  const customPermissions = this.permissions || [];
  
  return [...new Set([...basePermissions, ...customPermissions])];
};

// 检查是否有特定权限
User.prototype.hasPermission = function(permission) {
  const permissions = this.getPermissions();
  return permissions.includes('*') || permissions.includes(permission);
};

// 类方法
// 根据邮箱或用户名查找用户
User.findByEmailOrUsername = function(identifier) {
  return this.findOne({
    where: {
      [sequelize.Sequelize.Op.or]: [
        { email: identifier },
        { username: identifier }
      ]
    }
  });
};

// 根据邮箱验证令牌查找用户
User.findByEmailVerificationToken = function(token) {
  return this.findOne({
    where: {
      emailVerificationToken: token,
      emailVerificationExpires: {
        [sequelize.Sequelize.Op.gt]: new Date()
      }
    }
  });
};

// 根据密码重置令牌查找用户
User.findByPasswordResetToken = function(token) {
  return this.findOne({
    where: {
      passwordResetToken: token,
      passwordResetExpires: {
        [sequelize.Sequelize.Op.gt]: new Date()
      }
    }
  });
};

// 钩子函数
// 密码加密
User.beforeCreate(async (user) => {
  if (user.password) {
    user.password = await bcrypt.hash(user.password, config.security.bcryptRounds);
  }
});

User.beforeUpdate(async (user) => {
  if (user.changed('password')) {
    user.password = await bcrypt.hash(user.password, config.security.bcryptRounds);
  }
});

// 邮箱转小写
User.beforeCreate((user) => {
  if (user.email) {
    user.email = user.email.toLowerCase();
  }
});

User.beforeUpdate((user) => {
  if (user.changed('email')) {
    user.email = user.email.toLowerCase();
  }
});

// 用户名转小写
User.beforeCreate((user) => {
  if (user.username) {
    user.username = user.username.toLowerCase();
  }
});

User.beforeUpdate((user) => {
  if (user.changed('username')) {
    user.username = user.username.toLowerCase();
  }
});

// 记录用户创建日志
User.afterCreate((user) => {
  logger.business('用户注册', {
    userId: user.id,
    username: user.username,
    email: user.email,
    role: user.role
  });
});

// 记录用户更新日志
User.afterUpdate((user) => {
  const changes = user.changed();
  if (changes && changes.length > 0) {
    logger.business('用户信息更新', {
      userId: user.id,
      changes: changes.filter(field => !['updatedAt', 'lastLoginAt'].includes(field))
    });
  }
});

// 记录用户删除日志
User.afterDestroy((user) => {
  logger.business('用户删除', {
    userId: user.id,
    username: user.username,
    email: user.email
  });
});

module.exports = User;